﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SlgEntityTroop : BattleEntity
{
    private int m_iPos;
    public int Pos
    {
        get { return m_iPos; }
    }

    private List<SoldierVo> m_lisVo;
    public GameObject m_pGameObj;
    private NStateMachine<SlgEntityTroop> m_pStateMachine;
    public List<SlgEntitySoldier> m_lisSoldiers;
    private Dictionary<int, SlgEntitySoldier> m_dic_Index_Entity;
    //TroopMono m_pTroopMono;
    public bool m_bLeft;
    public bool m_bDeaded = false;
    private int m_iSoldierNum = 0;
    private int m_iNeedDeadNum = 0;
    public int INeedDeadNum
    {
        get
        {
            return m_iNeedDeadNum;
        }

        set
        {
            if(value > GetAliveSoldier().Count)
            {
                m_iNeedDeadNum = GetAliveSoldier().Count;
            }
            else
            {
                m_iNeedDeadNum = value;
            }
        }
    }

    public override void OnCreate(params object[] args)
    {
        m_iPos = (int)args[0];
        m_lisVo = (List<SoldierVo>)args[1];
        m_pGameObj = new GameObject();
        m_pGameObj.transform.position = Vector3.zero;
        m_pGameObj.transform.localScale = Vector3.one;
        m_pGameObj.transform.localEulerAngles = Vector3.zero;
        m_pGameObj.name = string.Format("Troop_{0}", m_iPos);
        m_bLeft = m_iPos <= SlgFightDef.c_iHeroIndexStep;
        Dictionary<string, NState<SlgEntityTroop>> states = new Dictionary<string, NState<SlgEntityTroop>>()
        {
            {SlgTroopState.c_sTroop_Move,SlgTroopState.s_pTroop_Move },
            {SlgTroopState.c_sTroop_Idle,SlgTroopState.s_pTroop_Idle }
            //{SlgTroopState.c_sTroop_Stop,SlgTroopState.s_pTroop_Stop },
            //{SlgTroopState.c_sTroop_Atk,SlgTroopState.s_pTroop_Atk }
        };
        m_pStateMachine = new NStateMachine<SlgEntityTroop>(this, states, "null");
        m_pStateMachine.ChangeState(SlgTroopState.c_sTroop_Idle);

        CreateSoldier();
        m_lisSoldiers = GetAllSoldier();
        //m_pTroopMono = m_pGameObj.AddComponent<TroopMono>();
        //m_pTroopMono.m_pTroop = this;
        
    }

    public override void OnUpdate(float deltaTime)
    {
        m_pStateMachine.OnUpdate();
    }

    public override void OnDestroy()
    {
        GameObject.Destroy(m_pGameObj);
    }

    private void CreateSoldier()
    {
        for (int i = 0; i < m_lisVo.Count; i++)
        {
            int num = ConvertNum(m_lisVo[i].hp,m_lisVo[i].config);
            m_iSoldierNum = num;
            for (int j = 0; j < num; j++)
            {
                SlgEntitySoldier soldier = BattleEntityFactory.Instance.CreateBtEntity<SlgEntitySoldier>() as SlgEntitySoldier;
                soldier.SetParent(this);
                soldier.OnCreate(m_lisVo[i], SlgBattleMgr.Instance.m_eRenderType, new Vector3(100, 0, 0), 0.3f);
                soldier.m_pGameObj.transform.SetParent(m_pGameObj.transform);
                InsertChild(soldier.Id);
            }
        }
        m_dic_Index_Entity = new Dictionary<int, SlgEntitySoldier>();
        Embattle(m_iPos);
    }

    //转换小兵个数
    private int ConvertNum(int bingli, SoliderInfo vo)
    {
        return vo.soliderMaxNum;
    }

    //根据pos来排布阵型
    private void Embattle(int pos)
    {
        List<SlgEntitySoldier> soldiers = GetAllSoldier();

        soldiers.Sort((x, y) =>
        {
            if (x.m_pVo.config.step > y.m_pVo.config.step)
            {
                return 1;
            }
            else if (x.m_pVo.config.step == y.m_pVo.config.step)
            {
                return 0;
            }
            else
            {
                return -1;
            }
        });
        for (int i = 0; i < soldiers.Count; i++)
        {
            m_dic_Index_Entity.Add(i, soldiers[i]);
            soldiers[i].TroopIndex = i;
            soldiers[i].m_pGameObj.transform.position = SlgFightUtil.GetTroopHeadPos(SlgBattleMgr.Instance.GetSideTroopPoss(m_bLeft), m_bLeft, pos) + 
                                                        SlgFightUtil.GetTroopFormation(soldiers[i].m_pVo.config.standId, soldiers.Count, i, soldiers[i].m_pVo.m_bleft);
        }
    }


    public Vector3 GetCenter()
    {
        Vector3 result = Vector3.zero;
        int count = 0;
        for (int i = 0; i < m_lisSoldiers.Count; i++)
        {
            if (!m_lisSoldiers[i].m_bDead)
            {
                count++;
                result += m_lisSoldiers[i].m_pGameObj.transform.position;
            }
        }
        if(count > 0)
            result = result / count;

        return result;
    }

    public List<SlgEntitySoldier> GetAllSoldier()
    {
        List<SlgEntitySoldier> soldiers = m_lisChild.ConvertAll<SlgEntitySoldier>(s => (SlgEntitySoldier)s);
        return soldiers;
    }

    public List<SlgEntitySoldier> GetAliveSoldier()
    {
        List<SlgEntitySoldier> alives = GetAllSoldier();
        for (int i = alives.Count - 1; i >= 0 ; i--)
        {
            if (alives[i].m_bDead)
            {
                alives.RemoveAt(i);
            }
        }
        return alives;
    }

    public bool IsAllDead()
    {
        return (GetAliveSoldier().Count <= 0);
    }

    public void ChangeState(string state,params object[] args)
    {
        m_pStateMachine.ChangeState(state, args);
    }

    public void RandomDoAttack()
    {
        //m_pTroopMono.StartCoroutine("RandomDoAction");
    }

    public int GetTroopDmg()
    {
        int result = 0;
        for (int i = 0; i < m_lisVo.Count; i++)
        {
            result += (m_lisVo[i].beforeHp - m_lisVo[i].afterHp);
        }
        return result;
    }

    public int GetTroopHp()
    {
        int result = 0;
        for (int i = 0; i < m_lisVo.Count; i++)
        {
            result += m_lisVo[i].hp;
        }
        return result;
    }

    public void RandomDeadByDmg(int dmg,bool randomDelay = false)
    {
        //Debug.LogFormat("TroopDead :{0}  {1}  {2}", dmg, GetTroopHp(), m_iSoldierNum);
        dmg = Dmg2DeadNum(dmg);
        //Debug.LogFormat("转换过后死多少个：{0}", dmg);
        RandomDeadByNum(dmg, randomDelay);
    }

    public void RandomDeadByNum(int deadNum,bool randomDelay = false)
    {
        List<SlgEntitySoldier> alives = GetAliveSoldier();
        if(alives.Count <= 0)
        {
            return;
        }

        if (deadNum > alives.Count)
        {
            Debug.Log("要死的人已经大于所有活着的人 就全部死吧");
            deadNum = alives.Count;
        }
        for (int i = 0; i < deadNum; i++)
        {
            int randomIndex = Random.Range(i, alives.Count - 1);
            //Debug.Log(randomIndex);
            bool toCamera = SlgBattleMgr.Instance.GetNeedFlyToCamera();
            SlgEntitySoldier temp = alives[randomIndex];
            alives[randomIndex] = alives[i];
            alives[i] = temp;
            if (randomDelay)
            {
                SlgBattleMgr.Instance.AddTimer(() =>
                {
                    temp.ChangeState(SlgSoldierState.c_sSoldier_Dead, toCamera);

                }, Random.Range(SlgFightDef.FDeadGapMin,SlgFightDef.FDeadGapMax));
            }
            else
            {
                temp.ChangeState(SlgSoldierState.c_sSoldier_Dead, toCamera);
            }
        }
    }

    public int Dmg2DeadNum(int dmg)
    {
        dmg = (int)((float)dmg / (float)GetTroopHp() * (float)m_iSoldierNum);
        return dmg;
    }

    public int DeadNum2Dmg(int deadNum)
    {
        deadNum = deadNum * GetTroopHp() / m_iSoldierNum;
        return deadNum;
    }

    public void AddNeedDeadNum(int dmg)
    {
        //Debug.Log("射箭死:  " + dmg+"   "+ Dmg2DeadNum(dmg));
        INeedDeadNum = Dmg2DeadNum(dmg);
    }

    public bool IsContainsTypeArmy(int armyType)
    {
        for (int i = 0; i < m_lisVo.Count; i++)
        {
            if(m_lisVo[i].config.soliderType == armyType)
            {
                return true;
            }
        }
        return false;
    }

    public bool AllChildInState(string state)
    {
        List<SlgEntitySoldier> alive = GetAliveSoldier();
        for (int i = 0; i < alive.Count; i++)
        {
            if (!alive[i].m_pStateMachine.IsInState(state))
            {
                return false;
            }
        }
        return true;
    }

    public void SetMaxSpeed(float maxSpeed)
    {
        List<SlgEntitySoldier> soldiers = GetAllSoldier();
        for (int i = 0; i < soldiers.Count; i++)
        {
            soldiers[i].m_pMoveComp.m_fMaxSpeed = maxSpeed;
        }
    }

    public SlgEntitySoldier GetSoldierByIndex(int index)
    {
        if (m_dic_Index_Entity.ContainsKey(index))
        {
            return m_dic_Index_Entity[index];
        }

        return null;
    }

    public void AliveDoAction(string state,params object[] args)
    {
        List<SlgEntitySoldier> alives = GetAliveSoldier();
        for (int i = 0; i < alives.Count; i++)
        {
            alives[i].ChangeState(state, args);
        }
    }
}

public class SlgTroopState
{
    //public const string c_sTroop_Atk = "troop_atk";
    public const string c_sTroop_Move = "troop_move";
    public const string c_sTroop_Idle = "troop_idle";

    //public static TroopStateAtk s_pTroop_Atk = new TroopStateAtk();
    public static TroopStateMove s_pTroop_Move = new TroopStateMove();
    public static TroopStateIdle s_pTroop_Idle = new TroopStateIdle();
}
